<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Mapper\ChContactMapper;
use App\CustHub\Mapper\ChLockCustomerCodeMapper;
use App\CustHub\Mapper\ChLockCustomerCodeRecordMapper;
use App\CustHub\Model\ChContact;
use Carbon\Carbon;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Paginator\LengthAwarePaginator;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use Mine\MineModel;
use function Hyperf\Collection\collect;

class ChLockCustomerCodeService extends AbstractService
{
    #[Inject]
    protected ChLockCustomerCodeRecordMapper $recordMapper;

    public $mapper;

    public function __construct()
    {
        $this->mapper = new ChLockCustomerCodeMapper();
    }

    public function getLockCustomerCodeList($params)
    {
        $uid = (int)$params['uid'];
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;
        $query = $this->mapper->model::query()
            ->select([
                'ch_lock_customer_code.id',
                'ch_lock_customer_code.code',
                'ch_lock_customer_code.created_at',
                'cu.nickname as user_name',
                'ccc.channel_name  as channel_name'
            ])
            ->leftJoin('ch_user as cu', 'cu.id', '=', 'ch_lock_customer_code.uid')
            ->leftJoin('ch_channel_code as ccc', 'ccc.id', '=', 'ch_lock_customer_code.channel_code_id')
            ->where('ch_lock_customer_code.uid', $uid)
            ->when(!empty($params['channel_name']), function ($query) use ($params) {
                $query->where('ccc.channel_name', 'like', '%' . $params['channel_name'] . '%');
            })
            ->when(!empty($params['time_range']), function ($query) use ($params) {
                $timeRange = explode(',', $params['time_range']);
                $start = Carbon::parse($timeRange[0])->startOfDay();
                $end = Carbon::parse($timeRange[1])->endOfDay();
                $query->whereBetween('ch_lock_customer_code.created_at', [$start, $end]);
            });

        $paginator = $query->paginate($pageSize);
        $items = $paginator->items();

        $codeIds = collect($items)->pluck('id')->filter()->unique()->toArray();

        $statistics = [];
        if(!empty($codeIds)){
            $statisticsCollection = $this->recordMapper->getCodeStatisticsByUid([
                'code_ids' => $codeIds,
                'uid' => $uid
                ]);

            // 遍历 MineCollection 并将数据整理成以 code_id 为键的数组
            foreach ($statisticsCollection as $statistic) {
                $codeId = $statistic->code_id;
                $statistics[$codeId] = [
                    'total_count' => $statistic->total_count,
                    'old_contact_count' => $statistic->old_contact_count,
                    'added_friend_count' => $statistic->added_friend_count
                ];
            }
        }

        $resultItems = array_map(function ($item) use ($statistics) {
            $codeId = $item->id;
            $item->statistics = $statistics[$codeId] ?? [
                'total_count' => 0,
                'old_contact_count' => 0,
                'added_friend_count' => 0
            ];
            return $item;
        }, $items);

        // 6. 返回分页结果
        return $this->mapper->setPaginate(
            new LengthAwarePaginator(
                $resultItems,
                $paginator->total(),
                $paginator->perPage(),
                $paginator->currentPage(),
                ['path' => LengthAwarePaginator::resolveCurrentPath()]
            )
        );
    }

    public function saveLockCustomerCode($params)
    {
        if (isset($params['page_cfg'])){
            $params['page_cfg'] = json_decode($params['page_cfg']);
        }
        return $this->mapper->save($params);
    }

    public function getLockCustomerCodeDetail($params)
    {
        $codeId = (int)$params['id'];

        $code = $this->mapper->model::query()
            ->with(['channelCode' => function($query) {
                $query->select([
                    'ch_channel_code.id', // 修正表别名
                    'ch_channel_code.code as channel_code',
                    'ch_channel_code.channel_name',
                    'ch_channel_code.uid',
                    'cu.nickname as user_name',
                    'cu.created_at as user_created_at'
                ])
                    ->leftJoin('ch_user as cu', 'ch_channel_code.uid', '=', 'cu.id'); // 使用实际表名
            }])
            ->findOrFail($codeId);

        // 合并属性到主对象
        if ($code->channelCode) {
            $code->channel_code = $code->channelCode->channel_code;
            $code->channel_name = $code->channelCode->channel_name;
            $code->user_name = $code->channelCode->user_name;
            $code->user_created_at = $code->channelCode->user_created_at;
            unset($code->channelCode);
        }

        return $code;
    }

    public function updateLockCustomerCode(array $params)
    {
        return $this->mapper->update($params['id'],$params);
    }

    public function deleteLockCustomerCode($params)
    {
        return $this->mapper->delete((array)$params['id']);
    }

    public function handleLockCustomer(array $params)
    {
        $codeId = $params['id'] ?? '';
        $userId = $params['user_id'] ?? null;

        if (!$codeId) {
            throw new NormalStatusException('缺少锁客码标识');
        }

        // 1. 查询锁客码配置
        $lockCode = $this->mapper->findById($codeId);
        if (!$lockCode) {
            throw new NormalStatusException('未找到对应锁客码');
        }

        // 2. 判断是否已添加企业微信成员
        $contacts = $this->checkIfContactAdded($userId, $lockCode->uid);

        if (!empty($contacts)) {
            // 3. 已添加 → 根据 display_mode 返回内容
            return $this->handleAddedUser($lockCode, $contacts,$userId);
        } else {
            // 4. 未添加 → 返回关联的渠道活码
            return $this->handleNewUser($lockCode,$userId);
        }
    }

    public function addTask($contact)
    {
        $uid = $contact->uid;
        $userId = $contact->user_id;
        $record = $this->recordMapper->findByUidAndUserId($uid, $userId);
        if ($record) {
            $this->recordMapper->update($record->id, ['is_add_friend' => 1]);
        }
    }

    /**
     * 判断是否已添加企业微信成员
     */
    private function checkIfContactAdded(?string $userId, $uid):array
    {
        if (!$userId) {
            return [];
        }

        // 示例：调用服务判断是否为企业微信联系人
        $contactMapper = container()->get(ChContactMapper::class);
        $contacts = $contactMapper->findByUserIdAndUid($userId, $uid)->toArray();

        return $contacts ?? [];
    }

    /**
     * 已添加用户处理逻辑
     */
    private function handleAddedUser(object $lockCode,$contacts,$userId)
    {
        $this->recordMapper->save([
            'uid' => $lockCode->uid,
            'main_uid' => $lockCode->main_uid,
            'code_id' => $lockCode->id,
            'user_id' => $userId,
            'is_add_friend' => 0,
            'is_new_contact' => 0
        ]);

        switch ($lockCode->display_mode) {
            case 0:
                return [
                    'type' => 'qrcode',
                    'url' => $this->getRobotQrCode($lockCode, $contacts)
                ];
            case 1:
                return [
                    'type' => 'redirect',
                    'url' => $lockCode->display_cfg
                ];
            default:
                throw new NormalStatusException('不支持的显示模式');
        }
    }

    /**
     * 未添加用户处理逻辑
     */
    private function handleNewUser(object $lockCode,$userId)
    {
        $channelCodeId = $lockCode->channel_code_id;
        if (!$channelCodeId) {
            throw new NormalStatusException('未配置关联渠道码');
        }

        $this->recordMapper->save([
            'uid' => $lockCode->uid,
            'main_uid' => $lockCode->main_uid, // 锁客码所属主账号
            'code_id' => $lockCode->id,
            'user_id' => $userId,
            'is_add_friend' => 0,
            'is_new_contact' => 1
        ]);

        // 查询 ch_channel_code 获取活码详情
        $channelCode = $this->channelCodeService->getCodeDetail(['id' => $channelCodeId]);

        return [
            'type' => 'channel_code',
            'data' => $channelCode
        ];
    }

    private function getRobotQrCode(object $code, array $contacts)
    {
        $cfg = $code->display_cfg;

        // 提取 contact IDs
        $contactIds = collect($contacts)->pluck('id')->toArray();
        if (empty($contactIds)) {
            return null;
        }

        // 初始化每个联系人的 tag_count 为 0
        $defaultTags = array_fill_keys($contactIds, (object)['tag_count' => 0]);

        // 查询每个联系人的标签数量
        $result = DB::table('ch_contact_corp_tag')
            ->select('contact_id', DB::raw('COUNT(corp_tag_id) as tag_count'))
            ->whereIn('contact_id', $contactIds)
            ->groupBy('contact_id')
            ->get()
            ->keyBy('contact_id');

        // 合并默认值和查询结果
        $mergedResult = [];
        foreach ($contactIds as $contactId) {
            $mergedResult[$contactId] = $result->get($contactId, (object)['tag_count' => 0]);
        }

        // 构建候选联系人列表
        $candidates = [];
        foreach ($contacts as $contact) {
            $contactId = $contact['id'] ?? null;
            if (!$contactId) continue;

            $contact['tag_count'] = (int)($mergedResult[$contactId]->tag_count ?? 0);
            $candidates[] = $contact;
        }

        if (empty($candidates)) {
            return null;
        }

        // 合并排序逻辑：先按 tag_count 降序，再根据 cfg 决定 create_time 升序或降序
        usort($candidates, function ($a, $b) use ($cfg) {
            $tagDiff = $b['tag_count'] <=> $a['tag_count'];
            if ($tagDiff !== 0) {
                return $tagDiff;
            }

            return $cfg === 0
                ? ($a['create_time'] ?? '') <=> ($b['create_time'] ?? '')
                : ($b['create_time'] ?? '') <=> ($a['create_time'] ?? '');
        });

        if (empty($candidates)) {
            return null;
        }

        $topCandidate = reset($candidates);
        $robotId = $topCandidate['robot_id'] ?? null;

        if (!$robotId) {
            return null;
        }

        $robotService = container()->get(ChRobotService::class);
        return $robotService->getPersonalQRCode(['id' => $robotId]);
    }
}